﻿using System;
using System.Collections.Generic;
using System.IO;

namespace Xmlt.ViewEngine
{
    internal class XmlVirtualPathResolver : System.Xml.XmlUrlResolver
    {

        private string _basePath;

        private List<string> _referencedUris = new List<string>();

        public XmlVirtualPathResolver() : this(null) { }

        public XmlVirtualPathResolver(string basePath)
        {
            _basePath = basePath;
        }

        public override System.Net.ICredentials Credentials
        {
            set { }

        }

        public string[] ReferencedUris
        {
            get
            {
                return _referencedUris.ToArray();
            }
        }

        public void Reset()
        {
            _referencedUris.Clear();
        }

        public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
        {
            _referencedUris.Add(absoluteUri.Scheme == "file" || absoluteUri.IsFile ? absoluteUri.LocalPath : absoluteUri.ToString());

            bool preProcess = false;
            if (absoluteUri is UriEx)
            {
                string args = ((UriEx)absoluteUri).Args;
                System.Collections.Specialized.NameValueCollection argsCollection = System.Web.HttpUtility.ParseQueryString(args);

                if (argsCollection["p"] == "1")
                {
                    preProcess = true;
                }
            }
            if (preProcess)
            {
                MemoryStream ms = new MemoryStream();
                StreamWriter sw = new StreamWriter(ms);

                sw.Write("<root><![CDATA[");
                sw.Flush();
                using (FileStream fs = new FileStream(absoluteUri.ToString().Substring(8), FileMode.Open, FileAccess.Read))
                {
                    byte[] buffer = new byte[1024];
                    int count = fs.Read(buffer, 0, buffer.Length);
                    while (count != 0)
                    {
                        ms.Write(buffer, 0, count);
                        count = fs.Read(buffer, 0, buffer.Length);
                    }
                    fs.Close();
                }

                sw.Write("]]></root>");
                sw.Flush();
                ms.SetLength(ms.Position);
                ms.Position = 0;

                return ms;
            }
            else
            {
                return base.GetEntity(absoluteUri, role, ofObjectToReturn);
            }

        }



        public override Uri ResolveUri(Uri baseUri, string relativeUri)
        {
            string args = "";
            if ((baseUri == null || baseUri.ToString() == "") && !string.IsNullOrEmpty(_basePath))
                baseUri = new Uri(_basePath);
            if (relativeUri.Contains("?"))
            {
                args = relativeUri.Substring(relativeUri.IndexOf("?"));
                relativeUri = relativeUri.Substring(0, relativeUri.IndexOf("?"));
            }
            if (relativeUri.StartsWith("file:///"))
            {
                return new UriEx(relativeUri, args);
            }
            else if (!relativeUri.StartsWith("http"))
            {
                string relativePath = System.Web.HttpContext.Current.Server.MapPath(relativeUri);
                if (File.Exists(relativePath))
                    return new UriEx("file:///" + relativePath, args);
                else if (!string.IsNullOrEmpty(_basePath))
                {
                    string path = Path.Combine(_basePath, relativeUri);
                    if (File.Exists(path))
                        return new UriEx(path, args);
                }
                relativeUri = System.Web.HttpContext.Current.Response.ApplyAppPathModifier(relativeUri);
            }
            Uri resolvedUri = base.ResolveUri(baseUri, relativeUri);
            return resolvedUri;
        }

        private class UriEx : Uri
        {

            private string _args;

            public UriEx(string path, string args)
                : base(path)
            {
                this._args = args;
            }

            public string Args
            {
                get
                {
                    return _args;
                }
            }
        }
    }

}
